package com.flin.icesilkworm.examination.bg.service.impl;

import static com.flin.icesilkworm.framework.jdbc.objects.CollectionUtils.toMap;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import static org.apache.commons.lang3.StringUtils.split;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.flin.icesilkworm.bgsys.api.ICommonApi;
import com.flin.icesilkworm.bgsys.sys.model.SystemUser;
import com.flin.icesilkworm.bgsys.sys.po.SystemResourceDo;
import com.flin.icesilkworm.bgsys.sys.po.SystemUserDo;
import com.flin.icesilkworm.examination.api.IExaminationApi;
import com.flin.icesilkworm.examination.bas.constant.ITheExaminationPaperConstant;
import com.flin.icesilkworm.examination.bas.constant.ITheExaminationPaperRelConstant;
import com.flin.icesilkworm.examination.bas.constant.ITheQuestionItemConstant;
import com.flin.icesilkworm.examination.bas.constant.ITheQuestionsAnswerConstant;
import com.flin.icesilkworm.examination.bas.constant.ITheTakeExamConstant;
import com.flin.icesilkworm.examination.bas.model.TheBasicExaminee;
import com.flin.icesilkworm.examination.bas.model.TheBasicTeacher;
import com.flin.icesilkworm.examination.bas.model.TheExaminationActivity;
import com.flin.icesilkworm.examination.bas.model.TheExaminationPaper;
import com.flin.icesilkworm.examination.bas.model.TheQuestionItem;
import com.flin.icesilkworm.examination.bas.model.TheQuestionsAnswer;
import com.flin.icesilkworm.examination.bas.model.TheTakeExam;
import com.flin.icesilkworm.examination.bas.po.TheBasicExamineeDo;
import com.flin.icesilkworm.examination.bas.po.TheBasicTeacherDo;
import com.flin.icesilkworm.examination.bas.po.TheExaminationPaperDo;
import com.flin.icesilkworm.examination.bas.po.TheExaminationPaperRelDo;
import com.flin.icesilkworm.examination.bas.po.TheExamineeDutyDo;
import com.flin.icesilkworm.examination.bas.po.TheExamineeGroupDo;
import com.flin.icesilkworm.examination.bas.po.TheQuestionItemDo;
import com.flin.icesilkworm.examination.bas.po.TheQuestionsAnswerDo;
import com.flin.icesilkworm.examination.bas.po.TheTakeExamDo;
import com.flin.icesilkworm.examination.bas.po.TheWhitePersonIpDo;
import com.flin.icesilkworm.examination.bg.service.IExamStandardService;
import com.flin.icesilkworm.examination.course.constant.ICourseLearnRecordConstant;
import com.flin.icesilkworm.examination.course.constant.ICourseLearnRecordDetailConstant;
import com.flin.icesilkworm.examination.course.constant.ICourseTeacherConstant;
import com.flin.icesilkworm.examination.course.model.CourseLearnRecord;
import com.flin.icesilkworm.examination.course.model.CourseLearnRecordDetail;
import com.flin.icesilkworm.examination.course.model.CourseTeacher;
import com.flin.icesilkworm.examination.course.po.CourseLearnRecordDetailDo;
import com.flin.icesilkworm.examination.course.po.CourseLearnRecordDo;
import com.flin.icesilkworm.examination.course.po.CourseTeacherDo;
import com.flin.icesilkworm.examination.gen.bas.po.GeneratedTheQuestionsAnswerDo.TheQuestionsAnswerAo;
import com.flin.icesilkworm.examination.gen.bg.service.impl.GeneratedExamStandardServiceImpl;
import com.flin.icesilkworm.framework.cache.RedisTemplateCache;
import com.flin.icesilkworm.framework.contants.AuthLoginUser;
import com.flin.icesilkworm.framework.contants.GlobalConstants;
import com.flin.icesilkworm.framework.jdbc.pojo.JavaNameMap;
import com.flin.icesilkworm.framework.logs.SybrisLog;
import com.flin.icesilkworm.framework.pojos.BaseModel;
import com.flin.icesilkworm.framework.pojos.CachaDataObject;
import com.flin.icesilkworm.framework.spring.SpringWebUtils;
import com.flin.icesilkworm.framework.utils.IpUtils;
import com.flin.icesilkworm.framework.utils.Md5Utils;
@Service("examStandardService")
@Transactional
@SuppressWarnings({ "serial", "rawtypes", "unchecked" })
public class ExamStandardServiceImpl extends GeneratedExamStandardServiceImpl implements ITheTakeExamConstant,IExamStandardService,ICommonApi{

	@Autowired
	private RedisTemplateCache redis;
	
	private Map<Long,CachaDataObject<ArrayList<Long>>> cacheRoleMap = new HashMap<>();
	
	@Resource(name="authLoginUserCache")
	private Map<String,AuthLoginUser> userMap;
	
	@Autowired
	protected IExaminationApi examinationApi;
	
	private SybrisLog log = new SybrisLog(this.getClass());

	//用户登录
	public Map<String,Object> loginByAdmin(String username,String password,String type){
		
		switch (type) {
			case "teacher":{//分管
				TheBasicTeacher teacher = TheBasicTeacherDo.get().teacherName(username).password(password).deleted(Boolean.FALSE).re().findForWhere();
				if(teacher != null) {
					return toLogin(teacher.getTeachId(),username,teacher.getTeacherCode(),teacher.getTeacherName(),3);
				}
				break;
			}
			case "course":{//讲师
				CourseTeacher teacher = CourseTeacherDo.get().teacherName(username).password(password)
							.asStop(Boolean.FALSE).deleted(Boolean.FALSE).re()
							.and(t->t.andTeacherStatusNotEqualTo( ICourseTeacherConstant.TEACHER_STATUS_STOPED))
							.findForWhere();
				if(teacher != null) {
					return toLogin(teacher.getCtId(),username,username,teacher.getTeacherName(),4);
				}
				break;
			}
			case "examinee":{
				TheBasicExaminee exam = TheBasicExamineeDo.get().theExameeName(username).password(password).deleted(Boolean.FALSE).re().findForWhere();
				if(exam != null) {
					return toLogin(exam.getExameeId(),username,username,exam.getTheExameeName(),2);
				}
				break;
			}
			case "admin":{
//				if("超级管理员".equals(username) && "7fa8282ad93047a4d6fe6111c93b308a".equals(password)) {
//					return toLogin(-1L, username, "XXXXXX", "超级管理员", 1);
//				}
				SystemUser user = SystemUserDo.create().where(t->t.andUserNameEqualTo(username).andUserPassEqualTo(password).andDeletedEqualTo(Boolean.FALSE)).findForWhere();
				if(user != null) {
					return toLogin(user.getUserId(),username,user.getUserName(),user.getDisplayName(),1);
				}
				break;
			}
			default: break;
		}
		
		
		return toMap("error","登录失败");
	}

	
	private Map<String, Object> toLogin(Long id,String username,String cardID,String realName,long type) {
		AuthLoginUser<HashMap<String,String>> authUser = new AuthLoginUser();
		authUser.setUser(new HashMap<String,String>(){ {
				put("userName",username);
				put("userMobile",realName);
				put("idCard",cardID);
				put("account",username);
				put(GlobalConstants.CURR_USER_ID,id + "");
				put(GlobalConstants.CURR_USER_NAME,username);
				put("role",type + "");//1-超级管理员 2-考生 3-教师
			 
		} });
		authUser.setUserId(id);
		if("1".equals(type)){ 
			authUser.setAccessAgree(true); 
		} else {
			authUser.setAccessAgree(false);
		}
		
		authUser.setJsessionid(SpringWebUtils.getRequest().getSession().getId());
		String token = Md5Utils.encrypByMd5(authUser.getUser().toString() + "_SYS");
		authUser.setToken(token); 
		Set<String> roleSet = new HashSet<>();
		CachaDataObject<ArrayList<Long>> actList = getOrCreate(cacheRoleMap, type, ()-> new CachaDataObject<>(3600_000));
		ArrayList<Long> finalActList = actList.execute(()->{
			ArrayList<Long> f =  new ArrayList<>();
			SystemResourceDo.create().where(t->t.joinSystemRoleRelativeOnQueryRolesByUsing()
					.andRoleIdEqualTo(type)).queryForWhere()
						.forEach(t->new SystemResourceDo(t)
							.queryResourceChildrenByUsing()
							.forEach(n->new SystemResourceDo(n).updateAuthToList(f)
					));
			return f;
		});
		
		roleSet.add(type + "");
		authUser.setAclSet(finalActList );
		authUser.setRoleSet(roleSet);
		redis.set(GlobalConstants.TOKEN_NAME + authUser.getToken(), JSONObject.toJSONString(authUser),24 * 3600);
		userMap.put(token, authUser);
		return  toMap("token",token,"msg","登录成功!","code","OK","userId",SpringWebUtils.getUserId());
	}

	public Map<String, Object> joinExamTake(TheTakeExam takeExam) {	
		TheTakeExamDo takeExamDo = new TheTakeExamDo(takeExam);
		String remoteAddr = IpUtils.getIpAddr(SpringWebUtils.getRequest() );
		TheExaminationActivity activity = takeExamDo.getActiIdObject();
		if(activity == null) return toMap("error","不存在该活动");
		if(Boolean.TRUE.equals(activity.getAsStop())){
			return toMap("error","已经暂停或者结束该考试");
		}
		if(activity.getActiviStartTime() != null && activity.getActiviStartTime().getTime() > System.currentTimeMillis()){
			return toMap("error","考试尚未开始！");
		}
		if(activity.getActiviEndTime() != null&& activity.getActiviEndTime().getTime() < System.currentTimeMillis()){
			return toMap("error","开始已经结束");
		}
		if(Boolean.TRUE.equals(activity.getAsWhite()) && !TheWhitePersonIpDo.get().ip(remoteAddr).asUsed(Boolean.TRUE).re().exists()){
			return toMap("error","IP[" + remoteAddr + "]不在白名单内!");
		}
		if(Boolean.TRUE.equals(activity.getAsLimitIp()) && isNotEmpty(activity.getLimitIpRules())){
			String ips [] = activity.getLimitIpRules().split(";");
			String [] sources =split(remoteAddr,'.');
			E:{
				F:for(String ip : ips){
					String strs [] =split(ip, '.');
					if(strs.length == 4){
						V:for(int i = 0; i < strs.length; i ++){
							String limit = strs[i].trim().replace(" ", "");
							String source = sources[i].trim();
							if(source.equals(limit)||"*".equals(limit) || limit.replace("{", ",").replace("}", ",").contains("," + source + ",")){
								continue V;
							}
							String [] rules = split(limit.substring(1,limit.length() - 1), ',');
							for(String rule : rules){
								if(rule.equals(source)){
									continue V;
								}
								int sourceInt = Integer.parseInt(source);
								if(rule.contains(":")){
									String [] rangestr = split(rule,':');
									int min = Integer.parseInt(rangestr[0]);
									int max = Integer.parseInt(rangestr[1]);
									if(min <= sourceInt && sourceInt <= max){
										continue V;
									}
								}
							}
							continue F;
						}
						break E;
					}
				}
				
				return toMap("error","地域不在白名单内，被限制使用");
			}
			
		}
		
		if(!(activity.getGroupId() != null && TheExamineeGroupDo.create().where(t->
			t.andGroupIdEqualTo(activity.getGroupId())
			 .joinTheExamineeGroupRelFkGroupId().andExamIdEqualTo(takeExam.getExameeId()))
			 .exists() //查询考生组
		   || activity.getDutyId() != null && TheExamineeDutyDo.create().where(t->
				t.andDutyIdEqualTo(activity.getDutyId())
				 .joinTheBasicExamineeFkDutyId().andExameeIdEqualTo(takeExam.getExameeId())
			 ).exists())	 //查询考生职务
		){
			return toMap("error","不在可以参加考试名单内"); 
		}
		TheTakeExam exam = takeExamDo.where(t->t.andExameeIdEqualTo(takeExam.getExameeId()).andActiIdEqualTo(takeExam.getActiId())).findForWhere();
		if(exam != null ){
			if(TAKE_STATUS_EXAMING.equals(exam.getTakeStatus())){
				if(exam.getEndTakeTime().getTime() < System.currentTimeMillis()){
					takeExamDo.setTakeId(exam.getTakeId())
							  .openRecord()
							  .setTakeStatus(TAKE_STATUS_END)
							  .update();
					return toMap("error","该试卷考试已经结束");  
				} 
			} else {
				return toMap("error","已经参加过该考试"); 
			}
		} else {
			takeExamDo.setDescObject(takeExam);
		}
		
		Map<String, Object> map = new HashMap<>();
		Map<Long,String> answerMap = new HashMap<>();
		TheExaminationPaper pager = takeExamDo.setPagerId(activity.getPagerId()).getPagerIdObject();
		Map<Long,String> replyedMap = new HashMap<>();
		
		if(exam == null){
			Map<String,List<Long>> cache = new HashMap<>();
			String examType = pager.getExamType();
			String rules = pager.getTheTitleRules();
			JSONArray array = JSONArray.parseArray(rules);
			int rand = (int)((takeExam.getExameeId() * 5 + pager.getPagerId() * 11)  % 100);
			Set<Long> itemSet = new HashSet<>();
			List<Integer>  maxScoreList = new ArrayList<>();
			switch(examType){
				case ITheExaminationPaperConstant.EXAM_TYPE_BY_SELF:{
					for(int i = 0 ; i < array.size(); i ++){
						JSONObject object = array.getJSONObject(i);
						List<Long> list = new ArrayList<>();
						//章节
						TheExaminationPaperRelDo.get()
							.titleId(object.getLong("id")).pagerId(pager.getPagerId()).re(ITheExaminationPaperRelConstant.ITEM_ID)
							.queryForWhere()
							.forEach(t->{
								if(itemSet.add(t.getItemId())){
									list.add(t.getItemId());
								}
							});
						
						String title = object.getString("title");
						
						map.put(title, forEach(TheQuestionItemDo.create().where(t->
								t.andDeletedEqualTo(Boolean.FALSE)
								 .andQuesItemIdIn(list)).queryForWhere(), 
							t->{
								if(t != null){
									if(!ITheQuestionItemConstant.QUES_TYPE_ANSWER.equals(t.getQuesType())){
										answerMap.put(t.getQuesItemId(), t.getRealAnswer());
									} else {
										answerMap.put(t.getQuesItemId(), "");
									}
									maxScoreList.add(t.getDefaultScore().intValue());
									t.setRealAnswer(null);//清空答案
								}
						}));
						cache.put(title, list);
//						items.forEach();
						
						
					}
					
					break;
				}
				case ITheExaminationPaperConstant.EXAM_TYPE_AUTO_SELECT:{
					List<TheQuestionItem> theQuestionItems = new ArrayList<>();
					for(int i = 0 ; i < array.size(); i ++){
						JSONObject object = array.getJSONObject(i);
						theQuestionItems.addAll(
							TheQuestionItemDo.create().where(t->
								t.andDeletedEqualTo(Boolean.FALSE)
								 .andQuesBankIdEqualTo(object.getLong("bankId"))
								 .orderBy("(%{0}.ques_item_id * " + rand + " % 99 + " + takeExam.getExameeId() + "% 45 + if(%{0}.question_Level = 'y',9999,0))","desc")
							)
							.and("random".equals(object.getString("dif")),t->t.andDefaultDifficultyEqualTo(object.getString("dif")))
							.and("random".equals(object.getString("quesType")),t->t.andQuesTypeEqualTo(object.getString("quesType")))
							.queryForWhere(0,object.getIntValue("number")));
						
						
					}
					
					theQuestionItems.forEach(t->{
						if(!itemSet.add(t.getQuesItemId())) return;
						List<TheQuestionItem> items = getOrCreate(map,t.getQuesType(),()->new ArrayList<>());// (List<TheQuestionItem>) map.get(t.getQuesType());
						items.add(t);
						List<Long> ids = getOrCreate(cache, t.getQuesType(), ()->new ArrayList<>());
						ids.add(t.getQuesItemId());
						if(!ITheQuestionItemConstant.QUES_TYPE_ANSWER.equals(t.getQuesType())){
							answerMap.put(t.getQuesItemId(), t.getRealAnswer());
						} else {
							answerMap.put(t.getQuesItemId(), "");
						}
						maxScoreList.add(t.getDefaultScore().intValue());
						t.setRealAnswer(null);//清空答案
	 				});
					break;
				}
			
			}
			int maxScore = (int) maxScoreList.parallelStream().collect(Collectors.summarizingInt(t->t)).getSum();
			long startTime = System.currentTimeMillis();
			exam = takeExamDo.setTheQuestionsSet(JSON.toJSONString(cache)) //缓存生成题目....
				 .setTheAnswer(JSON.toJSONString(answerMap)) //答案
				 .setJoinerIp(remoteAddr)//记录IP
				 .setPageScore(Boolean.TRUE.equals(pager.getAsExamMaxScore())?  new BigDecimal(pager.getExamTotalScore()):BigDecimal.ZERO)
		//			takeExamDo.setTotalScore(pager.getExamTotalScore())
				 .setStartTakeTime(new Timestamp(startTime))
				 .setMaxScore(new BigDecimal(maxScore))
				 .setEndTakeTime(new Timestamp(startTime + pager.getExamTime() * 60_000)) //预计结束时间
				 .setTakeStatus(TAKE_STATUS_EXAMING) //设置状态考试中...
				 .execute(th->th.save())//保存该记录
				 .getDescObject();
 
		} else {
			Map<String,List<Long>> cache = JSONObject.parseObject(exam.getTheQuestionsSet(), new TypeReference<Map<String,List<Long>>>(){});
			if(cache != null){
				cache.forEach((k,a)->{
					map.put(k,TheQuestionItemDo.create().where(t->
						t.andDeletedEqualTo(Boolean.FALSE)
						 .andQuesItemIdIn(a))
					  .queryForWhere()
					  .stream().map(t->{t.setRealAnswer(null);return t;})
					  .collect(Collectors.toList())
					  
					);
				});
			}
			if(exam.getJoinerIp() == null) exam.setJoinerIp("");
			if(!exam.getJoinerIp().contains(remoteAddr)){
				TheTakeExamDo.set(exam.getTakeId()).openRecord().joinerIp(exam.getJoinerIp() + "," + remoteAddr).re()
					 .update();
			}
			TheQuestionsAnswerDo.get().takeId(exam.getTakeId()).re()
				.and(t->t.setAttribute(ITheQuestionsAnswerConstant.EXAM_ITEM_ID,ITheQuestionsAnswerConstant.REPLY_ANSWER))
				.queryForWhere().forEach(t->replyedMap.put(t.getExamItemId(), t.getReplyAnswer()));
		}
		
		map.put("___",toMap(
				"replyed",replyedMap,//已经回答的内容
				"isRand",pager.getAtSelectRandom(),//随机
				"takeId",exam.getTakeId(),//主键
				"actiName",activity.getActivityName(),
				"startTime",exam.getStartTakeTime().getTime(),
				"paperName",pager.getPaperName(),
				"examTime",pager.getExamTime(),
				"examTotalScore",pager.getExamTotalScore(),
				"atSelectRandom",pager.getAtSelectRandom()
		));
		
		return map;
	}

	public Map<String, Object> recordVolume(List<TheQuestionsAnswer> theQuestionsAnswers, Long userId, Boolean endTakeExam,Long takeId) {
		
		if(theQuestionsAnswers != null){
			for(TheQuestionsAnswer answer : theQuestionsAnswers){
				if(answer != null){
					TheQuestionsAnswer dbObject = TheQuestionsAnswerDo.get()
							.takeId(answer.getTakeId())
							.examItemId(answer.getExamItemId()).re().findForWhere();
					if(dbObject != null){
						if(!(dbObject.getReplyAnswer() != null && answer.getReplyAnswer() != null && dbObject.getReplyAnswer().trim().equals(answer.getReplyAnswer()))){
//						} else {
							TheQuestionsAnswerDo.set(dbObject.getAnswerId())//.openRecord()
								.replyAnswer(answer.getReplyAnswer())
								.re()
//								.setAnswerId(dbObject.getAnswerId())
								.update();
						}
					} else {
						new TheQuestionsAnswerDo(answer).save();
					}
				}
				
			}
			
			if(Boolean.TRUE.equals(endTakeExam) && takeId != null){
				//打分
				List<TheQuestionsAnswer> answer =TheQuestionsAnswerDo.get().takeId(takeId).re().queryForWhere();
				
				TheTakeExam takeExam = TheTakeExamDo.get().takeId(takeId).re().findForWhere();
				
				if(takeExam == null || takeExam.getExameeId() != userId){
					return toMap("error","应试考生不正确");
				}
				
				String theAnswer = takeExam.getTheAnswer();
				BigDecimal total = new BigDecimal(0);
//				System.out.println(theAnswer);
				if(theAnswer != null){
					boolean needViewed = Boolean.FALSE;
					Map<Long,String> results = JSONObject.parseObject(theAnswer,new TypeReference<Map<Long,String>>(){});
					for(TheQuestionsAnswer an : answer){
						TheQuestionsAnswerAo ao = TheQuestionsAnswerDo.set(an.getAnswerId()).openRecord();
						String result = results.get(an.getExamItemId());
//						if(result == null){
						TheQuestionItem item = TheQuestionItemDo.get().quesItemId(an.getExamItemId())
								.re(ITheQuestionItemConstant.DEFAULT_SCORE,ITheQuestionItemConstant.REAL_ANSWER).findForWhere();
						if(item != null) result = item.getRealAnswer();
//						}
						if(result != null){
							if(result.trim().length() > 0){
								//除了多选外
								if(an.getReplyAnswer() != null && an.getReplyAnswer().trim().equals(result.trim())){
									ao.asRight(true).scores(new BigDecimal(item.getDefaultScore()));
								} else {
									ao.asRight(Boolean.FALSE).scores(BigDecimal.ZERO);
								}
							
								ao.responseTime(new Timestamp(System.currentTimeMillis()))
								  .changeBookWay(ITheQuestionsAnswerConstant.CHANGE_BOOK_WAY_AUTO_BOOK);
							} else {
								needViewed = true;
								ao.changeBookWay(ITheQuestionsAnswerConstant.CHANGE_BOOK_WAY_PERSON_BOOK) 
								  .scores(BigDecimal.ZERO);
							}
							ao.re() .update();
							BigDecimal bigDe = ao.re().getScores();
							total = total.add(bigDe != null ? bigDe : BigDecimal.ZERO);
						}
					}
					BigDecimal maxScore = takeExam.getMaxScore();
					BigDecimal pagerScore = takeExam.getPageScore();
					BigDecimal realMaxScore = maxScore;
					if(pagerScore != null && maxScore.intValue() > 0 && pagerScore.intValue() != 0){
						total = total.divide(maxScore,3,BigDecimal.ROUND_CEILING).multiply(pagerScore);
						realMaxScore = pagerScore;
					}
					
					TheTakeExamDo.set(takeId).openRecord()
						.takeStatus(needViewed ? ITheTakeExamConstant.TAKE_STATUS_END: ITheTakeExamConstant.TAKE_STATUS_LOOKED)
						.submitTime(new Timestamp(System.currentTimeMillis()))
						.totalScore(total)
						.re()
						.update();
					
					return toMap("score","客观题得分" + decimalFormat(total.floatValue()) + "分,最大得分:" + decimalFormat(realMaxScore.floatValue()));
				}
				
			}
			
		}
		
		
		return null;
	}


	//考生学习课程
	public Map<String,Object> learningRecord(Long proId){
		
		Long userid = SpringWebUtils.getUserId();
		CourseLearnRecord record = CourseLearnRecordDo.get().examId(userid).proId(proId).deleted(Boolean.FALSE).re().findForWhere();
		Map<String,Object> map = examinationApi.learningRecord(userid, record, proId);
		if(map != null){
			return (Map<String, Object>) map.get("data");
		}
		return null;
		 
	}
	
	//考生学习章节
	public Map<String,Object> learningDetails(Long recordId,Long detailId,String content,Long time){
		
		Timestamp current =  new Timestamp(System.currentTimeMillis());
		
		if(detailId != null){
			CourseLearnRecordDetail detail = CourseLearnRecordDetailDo.get().detailId(detailId).deleted(Boolean.FALSE).re().findForWhere();
			if(detail != null){
				long endTime = 0L;
				Timestamp end = detail.getEndLearnTime();
				if(end == null) endTime = detail.getBeginLearnTime().getTime();
				else endTime = detail.getEndLearnTime().getTime();
				if(time != null){
					new CourseLearnRecordDetailDo(detail).openRecord()
						.setEndLearnTime(new Timestamp(time + endTime))
						.setUsedTime(detail.getUsedTime() + time.intValue()/1000)
						.update();
				}
				
				CourseLearnRecordDo.set(recordId)
					.openRecord()
					.totalUsedTime(CourseLearnRecordDetailDo.get()
							.recordId(detail.getRecordId()).deleted(Boolean.FALSE)
							.re()
							.and(t->t.setAttributeEmpty().sum(ICourseLearnRecordDetailConstant.USED_TIME,"sum"))
							.listForWhere().stream().map(t->t.getInt("sum"))
							.findFirst().orElse(BaseModel.INTEGER_NULL)) //.get(0).getInt("sum"))
					.lastedLearnTime(current)
					.re()
					.update();
				
				if(detail.getLearnContent().equals(content)){//创建新的课程
					return toMap("code","success");
				}
				
			}  
		} 
		
		detailId = CourseLearnRecordDetailDo.set()
			.recordId(recordId)
			.learnContent(content)
			.beginLearnTime(current)
			.endLearnTime(current )
			.usedTime(0)
			.deleted(Boolean.FALSE)
			.learningIp(SpringWebUtils.getRequest().getRemoteHost())
			.re().save();
		
		return toMap("id",detailId);
	}
	
 


	//考生查看结果
	public Map<String,Object> viewTakeExam(Long takeId){
		
		Map<String, Object> map = new HashMap<>();
		
		TheTakeExam exam = TheTakeExamDo.get().takeId(takeId).re().findForWhere();
		
		if(exam == null) return toMap("error","找不到应试记录");
		
		if(ITheTakeExamConstant.TAKE_STATUS_EXAMING.equals(exam.getTakeStatus())){
			recordVolume(new ArrayList<>(),SpringWebUtils.getUserId(),true,exam.getTakeId());
		}
		
		TheTakeExamDo takeExamDo = new TheTakeExamDo(exam);
		TheExaminationPaper pager = takeExamDo.getPagerIdObject();
		TheExaminationActivity activity = takeExamDo.getActiIdObject();
		Map<Long,String> replyedMap = new HashMap<>();
		Map<Long,Boolean> rightMap = new HashMap<>();
		Map<String,List<Long>> cache = JSONObject.parseObject(exam.getTheQuestionsSet(), new TypeReference<Map<String,List<Long>>>(){});
		if(cache != null){
			cache.forEach((k,a)->{
				map.put(k,TheQuestionItemDo.create().where(t->
					t.andDeletedEqualTo(Boolean.FALSE)
					 .andQuesItemIdIn(a))
				  .queryForWhere()/*
				  .stream().map(t->{t.setRealAnswer(null);return t;})
				  .collect(Collectors.toList())*/
				  
				);
			});
		}
		TheQuestionsAnswerDo.get().takeId(exam.getTakeId()).re(ITheQuestionsAnswerConstant.AS_RIGHT,ITheQuestionsAnswerConstant.EXAM_ITEM_ID,ITheQuestionsAnswerConstant.REPLY_ANSWER)
			.queryForWhere().forEach(t->{
				rightMap.put(t.getExamItemId(), t.getAsRight());
				replyedMap.put(t.getExamItemId(), t.getReplyAnswer());
			});
		
		map.put("___",toMap(
				"right",rightMap,
				"take",exam,//问题界面
				"disabled",true,//关闭答题界面
				"replyed",replyedMap,//已经回答的内容
				"isRand",pager.getAtSelectRandom(),//随机
				"takeId",exam.getTakeId(),//主键
				"actiName",activity.getActivityName(),
				"startTime",exam.getStartTakeTime().getTime(),
				"paperName",pager.getPaperName(),
				"examTime",pager.getExamTime(),
				"examTotalScore",pager.getExamTotalScore(),
				"atSelectRandom",pager.getAtSelectRandom()
		));
		
		return map;
	}
	//统计数据
	public Map<String,Object> getStatisticInfos(){
		final Object N_GROUP_DAY = new String[] {"date_format(%{0}.lasted_upd_at ,'%Y-%m-%d')","day"};
		Calendar calender = today();
		long currentZeroTime = calender.getTimeInMillis() ;//今天0点时间
		//今天学习人数:
		long learnByToday = TheBasicExamineeDo.create()
				.where(t->t.joinCourseLearnRecordFkExamId()
						.joinCourseLearnRecordDetailFkRecordId()
						.andLastedUpdAtGreaterThan(new Timestamp(currentZeroTime)))
				.count();
		//今天参考人数
		long examByToday = TheTakeExamDo.create()
				.where(t->t.andLastedUpdAtGreaterThan(new Timestamp(currentZeroTime)))
				.count();
		
		long pager = TheExaminationPaperDo.create()
				.where(t->t.andDeletedDefaultWhereBy())
				.count();
		
		//近15天的情况
		long before15DayTime = currentZeroTime - 15 * 24 * 3600 * 1000;
		
		List<JavaNameMap<?>> examBefore15Day  =  TheTakeExamDo.create()
				.where(t->t.setAttributeEmpty()
						.count(ITheTakeExamConstant.TAKE_ID,"count")
						.addGroup(N_GROUP_DAY)
						.andLastedUpdAtGreaterThan(new Timestamp(before15DayTime))
				)
				.listForWhere();
		
		List<JavaNameMap<?>> learnBefore15Day =  CourseLearnRecordDo.create()
				.where(t->t.setAttributeEmpty()
//						.joinCourseLearnRecordFkExamId()
//						.joinCourseLearnRecordDetailFkRecordId()
						.count(ICourseLearnRecordConstant.EXAM_ID,"count")
						.addGroup(N_GROUP_DAY)
						.andLastedUpdAtGreaterThan(new Timestamp(before15DayTime))
				)
//		        .and(t->t.addGroup("%{0}.examee_id"))
				.listForWhere();
		
		calender.set(Calendar.DAY_OF_MONTH,1);
		//月初时间
		long startMonthTime = calender.getTimeInMillis() ;
		
		long onlineExamByMonth  =  TheTakeExamDo.create()
				.where(t->t.setAttributeEmpty()
						.andLastedUpdAtGreaterThan(new Timestamp(startMonthTime))
				).count();
		
		long onlineLearnByMonth =  TheBasicExamineeDo.create()
				.where(t->t.setAttributeEmpty()
						.joinCourseLearnRecordFkExamId()
						.joinCourseLearnRecordDetailFkRecordId()//.groups(N_GROUP_DAY)
						.andLastedUpdAtGreaterThan(new Timestamp(startMonthTime))
//						.count(ICourseLearnRecordDetailConstant.DETAIL_ID,"count")
				).count();
//				.listForWhere();
		
		List<JavaNameMap<?>> recordByMonthList = TheTakeExamDo.create()
				.where(t->t.setAttributeEmpty()
						 .groups(N_GROUP_DAY)
						.andLastedUpdAtGreaterThan(new Timestamp(startMonthTime))
						.count(ITheTakeExamConstant.TAKE_ID,"count")
				)
				.listForWhere();
		
			
		return toMap(
				"pager",pager,
				"examByToday",examByToday,
				"learnByToday",learnByToday,
				"learnBefore15Day",learnBefore15Day,
				"examBefore15Day",examBefore15Day,
				"onlineExamByMonth",onlineExamByMonth,
				"onlineLearnByMonth",onlineLearnByMonth,
				"recordByMonthList",recordByMonthList

		);
	}

	public SybrisLog getLog() { return this.log; }
}
